from typing import List


"""
122. 买卖股票的最佳时机 II
"""
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        """
        贪心算法
        https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/solutions/12625/best-time-to-buy-and-sell-stock-ii-zhuan-hua-fa-ji/
        """
        # profit = 0
        # for i in range(1, len(prices)):
        #     tmp = prices[i] - prices[i - 1]
        #     if tmp > 0: profit += tmp
        # return profit

        """
        动态规划
        考虑到「不能同时参与多笔交易」，因此每天交易结束后只可能存在手里有一支股票或者没有股票的状态。

        定义状态 dp[i][0] 
            表示第 i 天交易完后手里没有股票的最大利润，dp[i][1] 表示第 i 天交易完后手里持有一支股票的最大利润（i 从 0 开始）。
                考虑 dp[i][0] 的转移方程，如果这一天交易完后手里没有股票，那么可能的转移状态为前一天已经没有股票，即 dp[i−1][0]，
                或者
                前一天结束的时候手里持有一支股票，即 dp[i−1][1]，这时候我们要将其卖出，并获得 prices[i] 的收益。
            因此为了收益最大化，我们列出如下的转移方程：
                dp[i][0]=max{dp[i−1][0],dp[i−1][1]+prices[i]}
            
        再来考虑 dp[i][1] 表示第 i 天交易完后手里有股票的最大利润
                按照同样的方式考虑转移状态，那么可能的转移状态为前一天已经持有一支股票，即 dp[i−1][1]，  
                或者   
                前一天结束时还没有股票，即 dp[i−1][0]，这时候我们要将其买入，并减少 prices[i] 的收益。
            可以列出如下的转移方程：
                dp[i][1]=max{dp[i−1][1],dp[i−1][0]−prices[i]}
            
        对于初始状态，根据状态定义我们可以知道第 0 天交易结束的时候 dp[0][0]=0，dp[0][1]=−prices[0]。
        
        因此，我们只要从前往后依次计算状态即可。由于全部交易结束后，持有股票的收益一定低于不持有股票的收益，因此这时候 dp[n−1][0] 的收益必然是大于 dp[n−1][1] 的，最后的答案即为 dp[n−1][0]。
           1   2   3   4   5   6
        ________________________
        0｜0   0   4   4   7   7 
        1｜-7  -1  -1  1   3   3 
        作者：力扣官方题解
        链接：https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/solutions/476791/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode-s/
        """
        n = len(prices)
        dp = [[0 for _ in range(2)] for _ in range(n)]
        dp[0][0] = 0
        dp[0][1] = -prices[0]
        for i in range(1, n):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
        return dp[n - 1][0]


if __name__ == '__main__':
    prices = [7,1,5,3,6,4]
    print(Solution().maxProfit(prices))